package gu.sql2java;

import com.google.common.base.Function;

/**
 * 字符串模糊匹配类型
 * @author guyadong
 *
 */
public enum StringMatchType implements Function<String, String>{
	/**
	 * 精确匹配,
	 * 比较字符串是否与pattern完全相等
	 */
	EXACTLY_MATCH, 
	/**
	 * 字符串比较匹配,
	 * 比较字符串是否以pattern起始,如 'hello' 匹配 'hello,world'
	 */
	CMP_LEFT_MATCH,
	/**
	 * 字符串比较匹配,
	 * 比较字符串是否以pattern结尾,如 'world' 匹配 'hello,world'
	 */
	CMP_RIGHT_MATCH,
	/**
	 * 字符串比较匹配,
	 * 比较字符串是否包含pattern,如 'wo' 匹配 'hello,world'
	 */
	CMP_MATCH,
	/**
	 * 支持通配符的字符串比较匹配
	 * pattern中允许包含通配符('*','?'),'*'匹配任意0或多个字符,'?'匹配任意单个字符
	 * 比较字符串是否包含pattern,如 '1*2房' 匹配 '1032房间',匹配'10楼/32房间','1?2'匹配'1楼2单元','1?2房'不匹配'1032房间'
	 */
	WILDCARD_MATCH,
	/**
	 * 数字模糊匹配
	 * pattern必须全部为数字,
	 * 比较字符串中所有数字组成的字符串是否包含pattern数字序列,如'102'匹配'102-2房间','122'匹配'/1楼/2单元/2房间'
	 */
	DIGIT_FUZZY_MATCH,
	/**
	 * 左侧数字模糊匹配
	 * pattern必须全部为数字,
	 * 比较字符串中所有数字组成的字符串是否以pattern数字序列起始,如'102'匹配'10幛/22房间',但不匹配'/1楼/102房间'
	 */
	DIGIT_FUZZY_LEFT_MATCH,
	/**
	 * 右侧数字模糊匹配
	 * pattern必须全部为数字,
	 * 比较字符串中所有数字组成的字符串是否以pattern数字序列结尾,如'102'匹配'/1楼/102房间',但不匹配'102-2房间'
	 */
	DIGIT_FUZZY_RIGHT_MATCH,
	/**
	 * 带分隔符'/'的数字模糊匹配
	 * pattern必须为数字及分隔符'/','-','.',分隔符会被替换为'/',
	 * 比较字符串中所有数字组成的字符串是否包含pattern数字序列,如'1-102'匹配'1楼/102房间',不匹配'1楼/1102房间'
	 */
	DIGIT_SEP_FUZZY_MATCH, 
	/**
	 * 带分隔符'/'的左侧数字模糊匹配
	 * pattern必须为数字及分隔符'/','-','.',分隔符会被替换为'/',
	 * 比较字符串中所有数字组成的字符串是否以pattern数字起始,如'1-102'匹配'1楼/102-2房间',不匹配'1幢/1单元/102房间'
	 */
	DIGIT_SEP_FUZZY_LEFT_MATCH,
	/**
	 * 带分隔符'/'的右侧数字模糊匹配
	 * pattern必须为数字及分隔符'/','-','.',分隔符会被替换为'/',
	 * 比较字符串中所有数字组成的字符串是否以pattern数字结尾,如'1/102'匹配'1楼/1单元/102房间',不匹配'1幢/102-2房间'
	 */
	DIGIT_SEP_FUZZY_RIGHT_MATCH,
	/**
	 * 正则表达式匹配
	 * pattern为正则表达式,表达式,如果pattern不以'^'或'|$'结尾,会自动加上'^.*'开头和'.*$'结尾
	 * 比较字符串是否有满足pattern的正则匹配,如'1\d+'匹配'/1楼/102房间'
	 */
	REGEX_MATCH, 
	/**
	 * 全字模糊匹配
	 * pattern为要匹配的字符串序列
	 * 比较字符串是否混入pattern字符序列,如'12房'匹配'/1楼/102房间','王鹏'匹配'王小鹏','王鹏程','周王鹏','王鹏'
	 */
	FUZZY_MATCH;

	@Override
	public String apply(String input) {
		switch (this) {
		case WILDCARD_MATCH:
			return "^.*" + input.replace("*", ".*").replace("?", ".") + ".*$";
		case FUZZY_MATCH:
			return "^.*" + input.replaceAll(".", "$0.*");
		case DIGIT_FUZZY_MATCH:
			return "^.*" + input.replaceAll(".", "$0[^\\\\d]*") + ".*$";
		case DIGIT_FUZZY_LEFT_MATCH:
			return "^[^\\d]*" + input.replaceAll(".", "$0[^\\\\d]*") + ".*$";
		case DIGIT_FUZZY_RIGHT_MATCH:
			return "^.*" + input.replaceAll(".", "[^\\\\d]*$0") + "[^\\d]*$";
		case DIGIT_SEP_FUZZY_MATCH:
			// '.' '-' 为分隔符替换为 '/' 
			return "^.*" + input.replaceAll("[\\\\.\\\\-]+", "/").replaceAll(".", "$0[^\\\\d]*") + ".*$";
		case DIGIT_SEP_FUZZY_LEFT_MATCH:
			// '.' '-' 为分隔符替换为 '/' 
			return "^[^\\d]*" + input.replaceAll("[\\\\.\\\\-]+", "/").replaceAll(".", "$0[^\\\\d]*") + ".*$";
		case DIGIT_SEP_FUZZY_RIGHT_MATCH:
			// '.' '-' 为分隔符替换为 '/' 
			return "^.*" + input.replaceAll("[\\\\.\\\\-]+", "/").replaceAll(".", "[^\\\\d]*$0") + "[^\\d]*$";
		case REGEX_MATCH:
			if(!input.startsWith("^")){
				input = "^.*" + input; 
			}
			if(!input.endsWith("^")){
				input = input + ".*$"; 
			}
			return input;
		case CMP_LEFT_MATCH:
		case CMP_RIGHT_MATCH:
		case CMP_MATCH:
		case EXACTLY_MATCH:
		default:
			return input;
		}
	}
	public IStringMatchFilter createMatchFilter(){
		switch (this) {
		case CMP_LEFT_MATCH:
		case CMP_RIGHT_MATCH:
		case CMP_MATCH:
		case EXACTLY_MATCH:
			return new BaseFuzzyMatchFilter.DefaultStringMatcher(this);
		default:
			return new BaseFuzzyMatchFilter.RegexFilter().setPatternFormater(this);
		}
	}
}